package cn.wen.yaling.xo.service.impl;

import cn.wen.yaling.commons.constant.RedisConstants;
import cn.wen.yaling.commons.entity.MenuEntity;
import cn.wen.yaling.commons.enums.MenuStatus;
import cn.wen.yaling.commons.enums.PermissionStatus;
import cn.wen.yaling.commons.enums.SysParamsStatus;
import cn.wen.yaling.commons.service.RedisService;
import cn.wen.yaling.commons.utils.RedisUtils;
import cn.wen.yaling.commons.utils.ResultEntity;
import cn.wen.yaling.commons.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.wen.yaling.commons.utils.PageUtils;
import cn.wen.yaling.commons.utils.Query;

import cn.wen.yaling.xo.dao.PermissionDao;
import cn.wen.yaling.commons.entity.PermissionEntity;
import cn.wen.yaling.xo.service.PermissionService;


@Service("permissionService")
public class PermissionServiceImpl extends ServiceImpl<PermissionDao, PermissionEntity> implements PermissionService {

    @Autowired
    private PermissionDao permissionDao;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PermissionEntity> page = this.page(
                new Query<PermissionEntity>().getPage(params),
                new QueryWrapper<PermissionEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public Set<String> getAllPermissionByUsername(String account) {
        return permissionDao.selectAllPermissionValueByUsername(account);
    }

    @Override
    public ResultEntity getPermissionList() {
        List<PermissionVO> permissionList;
        // 1、先判断redis缓存中是否能命中缓存
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_PERMISSION_LIST)) {
            permissionList = redisUtils.getListCache(RedisConstants.CACHE_ADMIN_PERMISSION_LIST, PermissionVO.class);
        } else {
            // 2、缓存不命中则到db中获取
            // 1.获取全部的一级菜单
            List<PermissionEntity> levelPermissionList = getPermissions(0);
            // 2.获取到二级菜单
            permissionList = new ArrayList<>();
            levelPermissionList.forEach((item) -> {
                PermissionVO target = new PermissionVO();
                BeanUtils.copyProperties(item, target);
                List<PermissionEntity> childList = getPermissions(target.getId());
                List<PermissionVO> childs = new ArrayList<>();
                if (childList != null) {
                    childs = childList.stream().map((o) -> {
                        PermissionVO childTarget = new PermissionVO();
                        BeanUtils.copyProperties(o, childTarget);
                        return childTarget;
                    }).collect(Collectors.toList());
                }
                target.setChildPermissionList(childs);
                permissionList.add(target);
            });
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_ADMIN_PERMISSION_LIST, permissionList);
        }
        return ResultEntity.ok().put("data", permissionList);
    }

    @Override
    public ResultEntity addPermission(PermissionAddVO permissionAddVO) {
        PermissionEntity target = new PermissionEntity();
        BeanUtils.copyProperties(permissionAddVO, target);
        target.setCreateTime(new Date());
        target.setStatus(PermissionStatus.NORMAL_USE.getStatus());
        target.setUpdateTime(new Date());
        boolean res = permissionDao.insert(target) > 0;
        if (res) {
            // 删除权限相关缓存
            redisUtils.delPermissionListCache();
            return ResultEntity.ok();
        }
        return ResultEntity.error();
    }

    @Override
    public ResultEntity editPermission(PermissionUpdateVO permissionUpdateVO) {
        PermissionEntity target = new PermissionEntity();
        BeanUtils.copyProperties(permissionUpdateVO, target);
        target.setUpdateTime(new Date());
        boolean res = permissionDao.updateById(target) > 0;
        if (res) {
            // 删除权限相关缓存
            redisUtils.delPermissionListCache();
            return ResultEntity.ok();
        }
        return ResultEntity.error();
    }

    @Override
    public ResultEntity deleteBatchPermission(Integer permissionId) {
        PermissionEntity target = new PermissionEntity();
        target.setId(permissionId);
        target.setStatus(PermissionStatus.DELETED.getStatus());
        boolean res = permissionDao.updateById(target) > 0;
        if (res) {
            // 删除权限相关缓存
            redisUtils.delPermissionListCache();
            return ResultEntity.ok();
        }
        return ResultEntity.error();
    }

    @Override
    public ResultEntity getSimplePermissionList() {
        List<PermissionSimpleVO> permissionList;
        // 1、先判断redis缓存中是否能命中缓存
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_SIMPLE_PERMISSION_LIST)) {
            permissionList = redisUtils.getListCache(RedisConstants.CACHE_ADMIN_SIMPLE_PERMISSION_LIST, PermissionSimpleVO.class);
        } else {
            // 2、缓存不命中则到db中获取
            List<PermissionEntity> levelPermissionList = getPermissions(0);
            // 2.获取到二级菜单
            permissionList = new ArrayList<>();
            levelPermissionList.forEach((item) -> {
                PermissionSimpleVO target = new PermissionSimpleVO();
                BeanUtils.copyProperties(item, target);
                List<PermissionEntity> childList = getPermissions(item.getId());
                List<PermissionSimpleVO> childs = new ArrayList<>();
                if (childList != null) {
                    childs = childList.stream().map((o) -> {
                        PermissionSimpleVO childTarget = new PermissionSimpleVO();
                        BeanUtils.copyProperties(o, childTarget);
                        return childTarget;
                    }).collect(Collectors.toList());
                }
                target.setChildPermissionList(childs);
                permissionList.add(target);
            });
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_ADMIN_SIMPLE_PERMISSION_LIST, permissionList);
        }
        return ResultEntity.ok().put("data", permissionList);
    }

    @Override
    public ResultEntity getPermissionTreeList() {
        List<TreeVO> permissionList;
        // 1、先判断redis缓存中是否能命中缓存
        if (redisService.hasKey(RedisConstants.CACHE_ADMIN_TREE_PERMISSION_LIST)) {
            permissionList = redisUtils.getListCache(RedisConstants.CACHE_ADMIN_TREE_PERMISSION_LIST, TreeVO.class);
        } else {
            // 2、缓存不命中则到db中获取
            List<PermissionEntity> levelPermissionList = getPermissions(0);
            // 2.获取到二级菜单
            permissionList = new ArrayList<>();
            levelPermissionList.forEach((item) -> {
                TreeVO target = new TreeVO();
                target.setId(item.getId());
                target.setName(item.getPermissionsName());
                List<PermissionEntity> childList = getPermissions(item.getId());
                List<TreeVO> childs = new ArrayList<>();
                if (childList != null) {
                    childs = childList.stream().map((o) -> {
                        TreeVO childTarget = new TreeVO();
                        childTarget.setId(o.getId());
                        childTarget.setName(o.getPermissionsName());
                        return childTarget;
                    }).collect(Collectors.toList());
                }
                target.setChildren(childs);
                permissionList.add(target);
            });
            // 3、将db中的缓存获取到
            redisUtils.setListCache(RedisConstants.CACHE_ADMIN_TREE_PERMISSION_LIST, permissionList);
        }
        return ResultEntity.ok().put("data", permissionList);
    }

    private List<PermissionEntity> getPermissions(int parentId) {
        QueryWrapper<PermissionEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("status", PermissionStatus.DELETED.getStatus());
        queryWrapper.eq("parent_id", parentId);
        return permissionDao.selectList(queryWrapper);
    }

}